using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Rapier.Kodachi.Shared;
using Rapier.Kodachi.Engine;

namespace Rapier.Kodachi
{
    public partial class Display : Form, IDisplay
    {
        #region Data Members
        private Controller controller;
        private EntryMode lastEntryMode;
        #endregion

        #region Constructor
        public Display(Controller controller)
        {
            InitializeComponent();
            this.controller = controller;
            rtbItemText.SelectionAlignment = HorizontalAlignment.Center;
            rtbItemText.SelectionBackColor = Color.Black;
            rtbItemText.GotFocus += new EventHandler(rtbItemText_GotFocus);
            rtbItemText.Click += new EventHandler(rtbItemText_Click);

            tbTextEntry.KeyUp += new KeyEventHandler(tbTextEntry_KeyUp);
            tbTextEntry.KeyDown += new KeyEventHandler(tbTextEntry_KeyDown);

            KeyPreview = true;
            PreviewKeyDown += new PreviewKeyDownEventHandler(Display_PreviewKeyDown);
            KeyPress += new KeyPressEventHandler(Display_KeyPress);
            Deactivate += new EventHandler(Display_Deactivate);
        }

        void Display_Deactivate(object sender, EventArgs e)
        {
            controller.Sheath();
        }

       void tbTextEntry_KeyDown(object sender, KeyEventArgs e)
       {
          if ((e.KeyCode == Keys.Tab || e.KeyCode == Keys.Enter) && e.Control)
          {
             e.Handled = true;
             pbMain.BringToFront();
             tbTextEntry.SendToBack();
             tbTextEntry.Visible = false;
             panelMain.Visible = true;
          }
       }

       void Display_KeyPress(object sender, KeyPressEventArgs e)
       {
          controller.ProcessKeyDown(e);
       }

       void Display_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
       {
          controller.ProcessKeyDown(e);
       }

       void tbTextEntry_KeyUp(object sender, KeyEventArgs e)
       { 
          controller.ProcessKeyUp(e);
       }
       
       void rtbItemText_Click(object sender, EventArgs e)
       {
          this.Focus();
       }

       void rtbItemText_GotFocus(object sender, EventArgs e)
       {
          this.Focus();
       } 
        #endregion

        #region IDisplay Members
        public bool IsVisible
        {
            get { return Visible; }
        }

        private bool _ShowWaiting;
        public bool ShowWaiting
        {
            get
            {
                return _ShowWaiting;
            }
            set
            {
                _ShowWaiting = value;
            }
        }

        public string TextEntryString
        {
            get
            {
                return tbTextEntry.Text;
            }
            set
            {
                tbTextEntry.Text = value;
            }
        }

        public void Expose()
        {
            Show();
            Activate();
        }

        public void Sheath()
        {
            controller.DirectItemLookup.Reset();
            Close();
        }

        public void UpdateDisplay()
        {
            panelStashIndirect.Visible = (controller.IndirectItemLookup.SelectedItems.Length > 0);

            switch (controller.QueryMode)
            {
                case QueryMode.DirectItem:
                    UpdateDirectItem();
                    lastEntryMode = controller.DirectItemLookup.EntryMode;
                    break;
                case QueryMode.Action:
                    UpdateAction();
                    lastEntryMode = EntryMode.Normal;
                    break;
                case QueryMode.IndirectItem:
                    UpdateIndirectItem();
                    lastEntryMode = controller.IndirectItemLookup.EntryMode;
                    break;
                default:
                    break;
            }
        }
        #endregion

        #region Overrides
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            Size = new Size(300, 106);
        }

        protected override void OnKeyUp(KeyEventArgs e)
        {
            controller.ProcessKeyUp(e);
            base.OnKeyUp(e);
        }
        #endregion

        #region Private Methods
        private void UpdateDirectItem()
        {
            UpdateItem(controller.DirectItemLookup);
            lbMode.Text = "Direct Item";

            UpdateStashImages(controller.DirectItemLookup, panelStashDirect);
        }

        private void UpdateAction()
        {
            tbTextEntry.Visible = false;
            panelMain.Visible = true;
            lbArrow.Text = String.Empty;
            ILookupItem item = controller.ActionLookup.ActiveItem;
            UpdatePane(item);
            lbMode.Text = "Action";
        }

        private void UpdateIndirectItem()
        {
            UpdateItem(controller.IndirectItemLookup);
            lbMode.Text = "Indirect Item";

            UpdateStashImages(controller.IndirectItemLookup, panelStashIndirect);
        }

        private void UpdateItem(Lookup lookup)
        {
            if (lookup.EntryMode != lastEntryMode)
            {
                if (lookup.EntryMode == EntryMode.TextEntry)
                {
                    panelMain.Visible = false;
                    pbMain.Image = null;
                    pbMain.SendToBack();
                    tbTextEntry.Text = lookup.QueryString;
                    tbTextEntry.Visible = true;
                    tbTextEntry.BringToFront();
                    tbTextEntry.SelectionStart = tbTextEntry.Text.Length;
                    tbTextEntry.Focus();
                    return;
                }
                else
                {
                    pbMain.BringToFront();
                    tbTextEntry.SendToBack();
                    tbTextEntry.Visible = false;
                    panelMain.Visible = true;
                }
            }

            if (lookup.EntryMode == EntryMode.Normal)
            {
                ILookupItem item = lookup.ActiveItem;
                UpdatePane(item);
                if (item != null)
                {
                    bool showArrow = (item as Item).IsDrillable;
                    lbArrow.Text = ((item as Item).IsDrillable) ? ">" : String.Empty;
                }
                else
                {
                    lbArrow.Text = String.Empty;
                }
            }
        }

        private void UpdateStashImages(Lookup lookup, Panel stashPanel)
        {
            for (int i = 0; i < 10; i++)
            {
                PictureBox pbSmall = (PictureBox)stashPanel.Controls[i];

                if (lookup.SelectedItems.Length < i)
                    pbSmall.Image = null;
            }

            int startingIndex = lookup.SelectedItems.Length - 1;
            int endingIndex = Math.Max(0, startingIndex - 9);
            int firstImageIndex = 0;
            for (int i = startingIndex; i >= endingIndex; i--)
            {
                firstImageIndex++;
                if (firstImageIndex == 11)
                    break;

                PictureBox pbSmall = (PictureBox)stashPanel.Controls[firstImageIndex - 1];

                if (lookup.SelectedItems.Length > i)
                {
                    if (lookup.SelectedItems.Length == i + 1 && lookup.ActiveItem != null)
                        break;

                    UpdateImage(pbSmall, lookup.SelectedItems[i]);
                }
                else
                {
                    pbSmall.Image = null;
                }
            }
        }

        private void UpdatePane(ILookupItem item)
        {
           if (item == null)
           {
              rtbItemText.Text = "Type to search...";
              rtbItemText.SelectionStart = 0;
              rtbItemText.SelectionLength = rtbItemText.Text.Length;
              rtbItemText.SelectionColor = Color.White;
              lbDescription.Text = String.Empty;
              pbMain.Image = null;
              this.Refresh();
              return;
           }

            UpdateTextBlock(item);
            UpdateImage(pbMain, item);
            if (item is Item)
            {
                lbDescription.Text = item.Description;
            }
            else
            {
                lbDescription.Text = String.Empty;
            }
        }

        private void UpdateTextBlock(ILookupItem item)
        {
            string name = item.Name.ToUpper();
            string queryString = GetQueryString();

            int lastUsed = 0;

            rtbItemText.Text = String.Empty;
            rtbItemText.Text = name;
            rtbItemText.SelectionStart = 0;
            rtbItemText.SelectionLength = rtbItemText.Text.Length;
            rtbItemText.SelectionColor = rtbItemText.ForeColor;

            Char cUpper;
            foreach (char c in queryString)
            {
                cUpper = Char.ToUpper(c);
                int index = name.IndexOf(cUpper, lastUsed);
                rtbItemText.SelectionStart = index;
                rtbItemText.SelectionLength = 1;
                rtbItemText.SelectionColor = Color.Gold;
                lastUsed = index + 1;
            }
        }

       private string GetQueryString()
       {
          switch (controller.QueryMode)
          {
             case QueryMode.DirectItem:
                return controller.DirectItemLookup.QueryString;
             case QueryMode.Action:
                return controller.ActionLookup.QueryString;
             case QueryMode.IndirectItem:
                return controller.IndirectItemLookup.QueryString;
             default:
                return String.Empty;
          }
       }

        private void UpdateImage(PictureBox pictureBox, ILookupItem item)
        {
            pictureBox.Image = item.Image.GetThumbnailImage(pictureBox.Width, pictureBox.Height, null, IntPtr.Zero);
        }
        #endregion

    }
}